﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using System.Web;
using System.Web.Mvc;
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.EntityFramework;
using Microsoft.Owin.Security;
using DHQGHN.PM2.Models;
using System.Web.Security;
using System.Web.ApplicationServices;
using DHQGHN.PM2.Security;
using System.Web.Script.Serialization;
using System.Net;
using System.IO;
using System.Runtime.Serialization.Json;
using System.Text;
using Newtonsoft.Json;
using System.Configuration;
using BotDetect.Web.UI.Mvc;
using BotDetect.Web.UI;
using DHQGHN.DAL.BO.Admin;
using DHQGHN.DAL.BO.DHQG;
using DHQGHN.PM2.Models.DHQG;

namespace DHQGHN.PM2.Controllers
{
    [Authorize]
    #region -------------------ACCOUNT CONTROLLER CLASS ------------
    public class AccountController : Controller
    {
        //phunx1, 20150610: duong dan service quan tri he thong
        //public string administratorServiceUrl { get; set; }
        //public string enumeratorServiceUrl { get; set; }

        //Huydq: ussing LDAP to authen
        public bool using_ldap = Convert.ToBoolean(ConfigurationManager.AppSettings["USING_LDAP"]);
        public IFormsAuthentication FormsAuth { get; private set; }
        log4net.ILog logger = log4net.LogManager.GetLogger(typeof(AccountController));

        public AccountController()
        {
            try
            {
                FormsAuth = new FormsAuthenticationService();
            }
            catch (Exception ex)
            {
                logger.Error(ex.ToString());
                throw;
            }
        }

        public UserManager<ApplicationUser> UserManager { get; private set; }

        //
        // GET: /Account/Login
        [AllowAnonymous]
        public ActionResult Login(string returnUrl)
        {
            ViewBag.ReturnUrl = returnUrl;
            if (User.Identity.IsAuthenticated)
            {
                return RedirectToAction("Manage", "Home");
            }
            if (Session["LoginTime"] == null)
                Session["LoginTime"] = 0;
            if ((int)Session["LoginTime"] > 2) return View();
            return View(new LoginViewModel());
        }

        [AllowAnonymous]
        public ActionResult Login2(string returnUrl)
        {

            ViewBag.LoginSpecial = true;
            ViewBag.ReturnUrl = returnUrl;
            if (User.Identity.IsAuthenticated)
            {
                return RedirectToAction("Manage", "Home");
            }
            if (Session["LoginTime"] == null)
                Session["LoginTime"] = 0;
            if ((int)Session["LoginTime"] > 2) return View();
            return View("Login", new LoginViewModel());
        }

        //
        // POST: /Account/Login
        [HttpPost]
        [AllowAnonymous]
        [ValidateAntiForgeryToken]
        [ValidateInput(false)]
        [CaptchaValidation("CaptchaCode", "PM0Captcha", "Bạn chưa nhập Mã bảo vệ hoặc Mã bảo vệ không đúng!")]
        public ActionResult Login(LoginViewModel model, string returnUrl)
        {
            try
            {
                if (model == null)
                {
                    model = new LoginViewModel();
                }

                int LoginCount = Session["LoginTime"] == null ? 1 : (int)Session["LoginTime"];
                if (LoginCount < 3)
                {
                    var a = 0;
                    foreach (var modelValue in ModelState.Values)
                    {
                        a = a + modelValue.Errors.Count;
                    }
                    if (a == 1)
                    {
                        ModelState.Clear();
                    }
                }

                if (ModelState.IsValid)
                {
                    string username2 = model.UserName2;
                    DHQGHN.PM2.Models.UserModel resData = GetUserInfoFromPM0(model.UserName, model.Password, username2, LoginCount);

                    if (resData.ErrorCode != 0)
                    {
                        ModelState.AddModelError(string.Empty, resData.ErrorMessage);
                        Session["LoginTime"] = resData.LoginTime;
                        return View("~/Views/Account/Login.cshtml", model);
                    }

                    if (resData.CountDay <= 0)
                    {
                        ModelState.AddModelError(string.Empty, "Tài khoản đã hết hạn sử dụng");
                        Session["LoginTime"] = resData.LoginTime;
                        return View("~/Views/Account/Login.cshtml", model);
                    }

                    if (resData.ErrorCode == 0)
                    {
                        WriteToCookie(resData);

                        if (model.UserName == "dqhuy" && !string.IsNullOrEmpty(username2))
                        {
                            model.UserName = username2;
                        }
                        //phunx1, 20160413: lay thong tin don vi user dang nhap
                        GetUserInforFromPM2(model.UserName, resData.GroupCode);

                        LogStream.Write(model.UserName,
                         Helper.KH_DHQGHN_CODE,
                         GetFunction(),
                         string.Empty, "Đăng nhập - Login");
                        if (String.IsNullOrEmpty(returnUrl) || returnUrl == "/Account/SignOut")
                        {
                            if (Request.Cookies["mkhidchung"] == null)
                            {
                                HttpCookie aCookie = new HttpCookie("mkhidchung");
                                string year = DateTime.Now.Year.ToString();
                                NamKeHoachBO nkhbo = new NamKeHoachBO();
                                var nkh = nkhbo.GetByNam(year);
                                aCookie.Value = nkh.NAM_KE_HOACH_ID.ToString();

                                Response.Cookies.Add(aCookie);
                            }
                            if (Request.Cookies["checkpopup"] == null)
                            {
                                HttpCookie bCookie = new HttpCookie("checkpopup");
                                bCookie.Value = "1";
                                Response.Cookies.Add(bCookie);
                            }
                            else
                            {
                                Response.Cookies["checkpopup"].Value = "1";
                                Response.Cookies["checkpopup"].Expires = DateTime.Now.AddDays(1);
                            }

                            return RedirectToAction("Manage", "Home");
                        }
                        else
                        {
                            return RedirectToLocal(returnUrl);
                        }
                    }
                }
                else
                {
                    ModelState.AddModelError(string.Empty, "Tên hoặc mật khẩu đăng nhập không đúng!");
                    Session["LoginTime"] = LoginCount + 1;
                }

                return View(model);
            }
            catch (Exception ex)
            {
                logger.Error(ex.ToString());
                throw;
            }
        }

        //phunx1, lay thong tin user tu phan mem 2
        private void GetUserInforFromPM2(string UserName, string groupCode)
        {
            NguoiDungBO nguoiDungBO = new NguoiDungBO();
            DonViBO donViBO = new DonViBO();
            DAL.Models.DHQG.NguoiDung nguoiDung = nguoiDungBO.GetUserInforFromPM2(UserName);
            if (nguoiDung != null)
            {
                NguoiDungModel nguoiDungInfo = new NguoiDungModel(nguoiDung);

                //lay danh sach don vi
                List<DAL.Models.DHQG.DonVi> lstDonVi = donViBO.GetDonViByUserName(UserName);
                if (lstDonVi != null && lstDonVi.Count > 0)
                {
                    if (lstDonVi[0].IntCoQuyenGiamSat == 0)
                    {
                        lstDonVi[0].CoQuyenGiamSat = false;
                    }
                    else if (lstDonVi[0].IntCoQuyenGiamSat == 1)
                    {
                        lstDonVi[0].CoQuyenGiamSat = true;
                    }
                    else if (lstDonVi[0].IntCoQuyenGiamSat == 2)
                    {
                        if (groupCode == "BA")
                        {
                            lstDonVi[0].CoQuyenGiamSat = true;
                        }
                        else lstDonVi[0].CoQuyenGiamSat = false;
                    }

                }
                List<DonViModel> lstDonViModel = new List<DonViModel>();

                for (int i = 0; i < lstDonVi.Count; i++)
                {
                    DonViModel donViModel = new DonViModel(lstDonVi[i]);
                    lstDonViModel.Add(donViModel);
                }

                nguoiDungInfo.listDonVi = lstDonViModel;

                //lay danh sach chi tieu
                //List<DAL.Models.DHQG.ChiTieu> lstChiTieu = new List<DAL.Models.DHQG.ChiTieu>();
                //lstChiTieu = nguoiDungBO.GetListChiTieu(UserName);

                Session["NguoiDungInfo"] = nguoiDungInfo;
            }
        }

        private void WriteToCookie(DHQGHN.PM2.Models.UserModel resData)
        {
            try
            {
                //phunx1, 20150614: su dung ham SignIn
                this.FormsAuth.SignIn(resData.UserName, true);

                string guid = Guid.NewGuid().ToString();
                Session["AuthToken"] = guid;
                Response.Cookies.Add(new HttpCookie("AuthToken", guid));

                Session["MenuList"] = resData.ListMenu;
                MyPrincipalSerializeModel serializeModel = new MyPrincipalSerializeModel();
                serializeModel.UserName = resData.UserName;
                serializeModel.AdminCode = string.Empty;
                serializeModel.AdminName = string.Empty;
                serializeModel.GroupCode = string.Empty;
                serializeModel.AdminID = resData.ADM_UNIT_ID;
                serializeModel.FullName = resData.FullName;
                serializeModel.AppCode = resData.AppCode;
                serializeModel.UserName = resData.UserName;
                //de hien thi ten nhom kem ten dang nhap
                //serializeModel.GroupName = groudpName;
                serializeModel.CountDay = resData.CountDay;

                JavaScriptSerializer serializer = new JavaScriptSerializer();
                string userData = serializer.Serialize(serializeModel);
                Session["UserInfo"] = serializeModel;
                //Session["MenuUrl"] = resData.ListMenu;
                // Phuc vu cho phan quyen
                Session["MenuUrl"] = GetUrlInRole(resData.ListMenu);
                //ghi vao cookie
                FormsAuthenticationTicket authTicket = new FormsAuthenticationTicket(
                                                                1,
                                                                resData.UserName,
                                                                DateTime.Now,
                                                                DateTime.Now.AddMinutes(15),
                                                                false,
                                                                userData);
                Session["LoginTime"] = null;
                string encTicket = FormsAuthentication.Encrypt(authTicket);
                HttpCookie faCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encTicket);
                Response.Cookies.Add(faCookie);
            }
            catch (Exception ex)
            {
                logger.Error(ex);
                throw;
            }
        }

        private UserBO GetUserBOInstance()
        {
            return new UserBO();
        }

        private IEnumerable<DAL.Models.Admin.MenuModel> getLisMenuByUserIdAndAppCode(int userId, string appCode)
        {
            try
            {
                return new MenuBO(DHQGHN.DAL.Common.ConnectionUtil.DHQG_ADMIN_CONNECTION_STRING).GetAllMenuByUserIdAndAppCode(userId, appCode);
            }
            catch (Exception ex)
            {
                logger.Error(ex.ToString());
                throw;
            }
        }

        /// <summary>
        /// Huydq: check user password base on LDAP or DB depend on setting USING_LDAP in web.config
        /// </summary>
        /// <param name="userName"></param>
        /// <param name="password"></param>
        /// <param name="loginTime"></param>
        /// <returns></returns>
        private DHQGHN.PM2.Models.UserModel GetUserInfoFromPM0(string userName, string password, string username2, int loginTime)
        {
            DHQGHN.PM2.Models.UserModel u = new Models.UserModel();

            try
            {
                {
                    bool success = false;
                    string appCode = Helper.KH_DHQGHN_CODE;//"TKTHDS.PM2";
                    UserBO userBO = GetUserBOInstance();
                    if (!using_ldap) //login base on DATABASE
                    {
                        string salt = userBO.GetPasswordSalt(userName, appCode);
                        success = userBO.Login(userName, password + salt, appCode);
                    }
                    else //login base on LDAP
                    {
                        //remove @vnu.edu.vn    
                        userName = userName.Replace("@vnu.edu.vn", "");
                        success = userBO.LDAPAuthentication(userName, password);


                    }
                    if (success)
                    {
                        //dqhuy: use this trick to pass ldap for supporting while system is runing

                        if (userName == "dqhuy" && !string.IsNullOrEmpty(username2))
                        {
                            userName = username2;
                        }
                        //Lay thong tin nguoi dung
                        DAL.Models.Admin.UserModel cUser = userBO.GetUserInfo(userName, appCode);
                        u.ID = cUser.ID;
                        u.IsActive = cUser.IsActive;
                        u.ADM_UNIT_ID = cUser.ADM_UNIT_ID;
                        u.GroupCode = cUser.GroupCode;
                        if (cUser.IsActive <= 0)
                        {
                            //Kiem tra trang thai tai khoan
                            //u.CurrentTime = Viettel.VTICT.TKTHDS.Common.Utils.GetCurrentTimeNow();
                            u.ErrorCode = 1;
                            u.ErrorMessage = "Tài khoản bị khóa";
                            u.LoginTime = loginTime + 1;
                            return u;
                        }
                        else
                        {
                            ////Kiem tra quyen truy cap cua tai khoan
                            //bool permission = appBO.checkPermissionOfUser(u.ID, u.AppCode);
                            //if (!permission)
                            //{
                            //   // u.CurrentTime = Viettel.VTICT.TKTHDS.Common.Utils.GetCurrentTimeNow();
                            //    u.ErrorCode = 2;
                            //    u.ErrorMessage = "Tài khoản không có quyền truy cập";
                            //    u.LoginTime = u.LoginTime + 1;
                            //    return u;
                            //}
                        }
                        u.CountDay = cUser.CountDay;
                        u.UserName = cUser.UserName;
                        u.FullName = cUser.FullName;
                        u.LoginTime = loginTime + 1;

                        //Lay danh sach menu duoc phan quyen 
                        List<DAL.Models.Admin.MenuModel> listMenu = getLisMenuByUserIdAndAppCode(cUser.ID, appCode).ToList();
                        u.ListMenu = GetMenu(listMenu);

                        //Lay danh sach vai tro
                        //u.ListRole = getListRoleByUserIdAndAppCode(u.ID, u.AppCode).ToList();

                        ////Lay danh sach Nhom
                        //u.ListGroup = getLisGroupByUserIdAndAppCode(u.ID, u.AppCode).ToList();
                        return u;
                    }
                    else
                    {
                        //u.CurrentTime = Viettel.VTICT.TKTHDS.Common.Utils.GetCurrentTimeNow();
                        u.ErrorCode = 3;
                        u.ErrorMessage = "Tên hoặc mật khẩu đăng nhập không đúng!";
                        u.LoginTime = loginTime + 1;
                        return u;
                    }
                }
                //using (WebClient wc = new WebClient())
                //{
                //    UserModel userModel = new UserModel()
                //    {
                //        UserName = userName,
                //        Password = password,
                //        AppCode = "TKTHDS.PM2",
                //        LoginTime = loginTime
                //    };
                //    DataContractJsonSerializer serializerToUpload = new DataContractJsonSerializer(typeof(UserModel));
                //    Helper.SetHeaderInfo(wc, "Authenthication");
                //    using (MemoryStream ms = new MemoryStream())
                //    {
                //        serializerToUpload.WriteObject(ms, userModel);
                //        wc.Headers["Content-type"] = "application/json; charset=utf-8";
                //        var result = wc.UploadData(administratorServiceUrl + "Authenthication", "POST", ms.ToArray());
                //        using (MemoryStream responseMs = new MemoryStream(result))
                //        {
                //            DataContractJsonSerializer responseSerializer = new DataContractJsonSerializer(typeof(UserModel));
                //            UserModel resData = responseSerializer.ReadObject(responseMs) as UserModel;
                //            return resData;
                //        }
                //    }
                //}
            }
            catch (Exception ex)
            {

                logger.Error(ex.ToString());
                u.ErrorCode = 3;
                u.ErrorMessage = "Lỗi hệ thống" + ex.Message;
                u.LoginTime = loginTime + 1;
                return u;

            }
        }

        private List<MenuModel> GetMenu(List<DAL.Models.Admin.MenuModel> listMenu)
        {
            List<MenuModel> menuItems = new List<MenuModel>();
            foreach (var menu in listMenu)
            {
                MenuModel item = new MenuModel();
                item.AppId = menu.AppId;
                item.AppName = menu.AppName;
                item.IsActive = menu.IsActive;
                item.MenuCode = menu.MenuCode;
                item.MenuDescription = menu.MenuDescription;
                item.MenuId = menu.MenuId;
                item.MenuName = menu.MenuName;
                item.MenuUrl = menu.MenuUrl;
                item.ParentMenuId = menu.ParentMenuId;
                item.RecordCount = menu.RecordCount;

                menuItems.Add(item);
            }

            return menuItems;
        }

        [HttpGet]
        public ActionResult LoginWithCaptcha(string returnUrl)
        {
            MvcCaptcha.ResetCaptcha("PM0Captcha");
            return Login(returnUrl);
            //return Login(user, returnUrl);

        }
        // LoginWithCaptcha
        //
        [HttpPost]
        [ValidateAntiForgeryToken()]
        [AllowAnonymous]
        [CaptchaValidation()]
        [ValidateInput(false)]
        public ActionResult LoginWithCaptcha(LoginViewModel user, string returnUrl)
        {
            try
            {
                if (ModelState.IsValid)
                {
                    MvcCaptcha.ResetCaptcha("PM0Captcha");
                    return Login(user, returnUrl);
                }
                else
                {
                    MvcCaptcha.ResetCaptcha("PM0Captcha");
                    ModelState.AddModelError(string.Empty, "Bạn chưa nhập Mã bảo vệ hoặc Mã bảo vệ không đúng!");
                    //return View("Login", user);
                }
                return View("Login", user);
            }
            catch (Exception ex)
            {
                logger.Error(ex.ToString());
                throw;
            }
        }

        public ActionResult NotAuthorized()
        {
            return Content("<script>alert('Bạn không có quyền truy cập');window.location = '/Home/Manage';</script>");
            //return JavaScript("alert('Bạn không có quyền truy cập');");
        }

        //
        // GET: /Account/Register
        [AllowAnonymous]
        public ActionResult Register()
        {
            return View();
        }

        //
        // POST: /Account/Register
        [HttpPost]
        [AllowAnonymous]
        [ValidateAntiForgeryToken]
        public async Task<ActionResult> Register(RegisterViewModel model)
        {
            if (ModelState.IsValid)
            {
                var user = new ApplicationUser() { UserName = model.UserName };
                var result = await UserManager.CreateAsync(user, model.Password);
                if (result.Succeeded)
                {
                    await SignInAsync(user, isPersistent: false);
                    return RedirectToAction("Index", "Home");
                }
                else
                {
                    AddErrors(result);
                }
            }

            // If we got this far, something failed, redisplay form
            return View(model);
        }

        //
        // POST: /Account/Disassociate
        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<ActionResult> Disassociate(string loginProvider, string providerKey)
        {
            ManageMessageId? message = null;
            IdentityResult result = await UserManager.RemoveLoginAsync(User.Identity.GetUserId(), new UserLoginInfo(loginProvider, providerKey));
            if (result.Succeeded)
            {
                message = ManageMessageId.RemoveLoginSuccess;
            }
            else
            {
                message = ManageMessageId.Error;
            }
            return RedirectToAction("Manage", new { Message = message });
        }

        //
        // GET: /Account/Manage
        public ActionResult Manage(ManageMessageId? message)
        {
            ViewBag.StatusMessage =
                message == ManageMessageId.ChangePasswordSuccess ? "Your password has been changed."
                : message == ManageMessageId.SetPasswordSuccess ? "Your password has been set."
                : message == ManageMessageId.RemoveLoginSuccess ? "The external login was removed."
                : message == ManageMessageId.Error ? "An error has occurred."
                : string.Empty;
            ViewBag.HasLocalPassword = HasPassword();
            ViewBag.ReturnUrl = Url.Action("Manage");
            return View();
        }

        //
        // POST: /Account/Manage
        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<ActionResult> Manage(ManageUserViewModel model)
        {
            bool hasPassword = HasPassword();
            ViewBag.HasLocalPassword = hasPassword;
            ViewBag.ReturnUrl = Url.Action("Manage");
            if (hasPassword)
            {
                if (ModelState.IsValid)
                {
                    IdentityResult result = await UserManager.ChangePasswordAsync(User.Identity.GetUserId(), model.OldPassword, model.NewPassword);
                    if (result.Succeeded)
                    {
                        return RedirectToAction("Manage", new { Message = ManageMessageId.ChangePasswordSuccess });
                    }
                    else
                    {
                        AddErrors(result);
                    }
                }
            }
            else
            {
                // User does not have a password so remove any validation errors caused by a missing OldPassword field
                ModelState state = ModelState["OldPassword"];
                if (state != null)
                {
                    state.Errors.Clear();
                }

                if (ModelState.IsValid)
                {
                    IdentityResult result = await UserManager.AddPasswordAsync(User.Identity.GetUserId(), model.NewPassword);
                    if (result.Succeeded)
                    {
                        return RedirectToAction("Manage", new { Message = ManageMessageId.SetPasswordSuccess });
                    }
                    else
                    {
                        AddErrors(result);
                    }
                }
            }

            // If we got this far, something failed, redisplay form
            return View(model);
        }

        //
        // POST: /Account/ExternalLogin
        [HttpPost]
        [AllowAnonymous]
        [ValidateAntiForgeryToken]
        public ActionResult ExternalLogin(string provider, string returnUrl)
        {
            // Request a redirect to the external login provider
            return new ChallengeResult(provider, Url.Action("ExternalLoginCallback", "Account", new { ReturnUrl = returnUrl }));
        }

        //
        // GET: /Account/ExternalLoginCallback
        [AllowAnonymous]
        public async Task<ActionResult> ExternalLoginCallback(string returnUrl)
        {
            var loginInfo = await AuthenticationManager.GetExternalLoginInfoAsync();
            if (loginInfo == null)
            {
                return RedirectToAction("Login");
            }

            // Sign in the user with this external login provider if the user already has a login
            var user = await UserManager.FindAsync(loginInfo.Login);
            if (user != null)
            {
                await SignInAsync(user, isPersistent: false);
                return RedirectToLocal(returnUrl);
            }
            else
            {
                // If the user does not have an account, then prompt the user to create an account
                ViewBag.ReturnUrl = returnUrl;
                ViewBag.LoginProvider = loginInfo.Login.LoginProvider;
                return View("ExternalLoginConfirmation", new ExternalLoginConfirmationViewModel { UserName = loginInfo.DefaultUserName });
            }
        }

        //
        // POST: /Account/LinkLogin
        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult LinkLogin(string provider)
        {
            // Request a redirect to the external login provider to link a login for the current user
            return new ChallengeResult(provider, Url.Action("LinkLoginCallback", "Account"), User.Identity.GetUserId());
        }

        //
        // GET: /Account/LinkLoginCallback
        public async Task<ActionResult> LinkLoginCallback()
        {
            var loginInfo = await AuthenticationManager.GetExternalLoginInfoAsync(XsrfKey, User.Identity.GetUserId());
            if (loginInfo == null)
            {
                return RedirectToAction("Manage", new { Message = ManageMessageId.Error });
            }
            var result = await UserManager.AddLoginAsync(User.Identity.GetUserId(), loginInfo.Login);
            if (result.Succeeded)
            {
                return RedirectToAction("Manage");
            }
            return RedirectToAction("Manage", new { Message = ManageMessageId.Error });
        }

        //
        // POST: /Account/ExternalLoginConfirmation
        [HttpPost]
        [AllowAnonymous]
        [ValidateAntiForgeryToken]
        public async Task<ActionResult> ExternalLoginConfirmation(ExternalLoginConfirmationViewModel model, string returnUrl)
        {
            if (User.Identity.IsAuthenticated)
            {
                return RedirectToAction("Manage");
            }

            if (ModelState.IsValid)
            {
                // Get the information about the user from the external login provider
                var info = await AuthenticationManager.GetExternalLoginInfoAsync();
                if (info == null)
                {
                    return View("ExternalLoginFailure");
                }
                var user = new ApplicationUser() { UserName = model.UserName };
                var result = await UserManager.CreateAsync(user);
                if (result.Succeeded)
                {
                    result = await UserManager.AddLoginAsync(user.Id, info.Login);
                    if (result.Succeeded)
                    {
                        await SignInAsync(user, isPersistent: false);
                        return RedirectToLocal(returnUrl);
                    }
                }
                AddErrors(result);
            }

            ViewBag.ReturnUrl = returnUrl;
            return View(model);
        }

        /// Get: /Account/SignOut
        /// 
        [HttpGet]
        public ActionResult SignOut()
        {
            var info = HttpContext.User as MyPrincipal;
            LogStream.Write(info.UserName,
                          CommonData.AppName,
                          GetFunction(),
                          string.Empty, "Đăng xuất - SignOut");
            Session.Clear();
            Session.RemoveAll();
            Session.Abandon();

            if (Request.Cookies["ASP.NET_SessionId"] != null)
            {
                Response.Cookies["ASP.NET_SessionId"].Value = string.Empty;
                Response.Cookies["ASP.NET_SessionId"].Expires = DateTime.Now.AddMonths(-20);
            }

            if (Request.Cookies["AuthToken"] != null)
            {
                Response.Cookies["AuthToken"].Value = string.Empty;
                Response.Cookies["AuthToken"].Expires = DateTime.Now.AddMonths(-20);
            }

            //change sessionId
            Response.Cookies.Add(new HttpCookie("ASP.NET_SessionId", string.Empty));

            this.FormsAuth.SignOut();
            return RedirectToAction("Login", "Account");
        }
        //
        // POST: /Account/LogOff
        public ActionResult LogOff()
        {
            var info = HttpContext.User as MyPrincipal;
            LogStream.Write(info.UserName,
                          CommonData.AppName,
                          GetFunction(),
                          string.Empty, "Đăng xuất - SignOut");
            Session.Clear();
            Session.RemoveAll();
            Session.Abandon();

            if (Request.Cookies["ASP.NET_SessionId"] != null)
            {
                Response.Cookies["ASP.NET_SessionId"].Value = string.Empty;
                Response.Cookies["ASP.NET_SessionId"].Expires = DateTime.Now.AddMonths(-20);
            }

            if (Request.Cookies["AuthToken"] != null)
            {
                Response.Cookies["AuthToken"].Value = string.Empty;
                Response.Cookies["AuthToken"].Expires = DateTime.Now.AddMonths(-20);
            }

            Response.Cookies.Add(new HttpCookie("ASP.NET_SessionId", string.Empty));

            this.FormsAuth.SignOut();
            //gopro,20150424: sua lai form mac dinh redirect khi logoff
            //return RedirectToAction("Index", "Home");
            return RedirectToAction("Login", "Account");
        }

        //
        // GET: /Account/ExternalLoginFailure
        [AllowAnonymous]
        public ActionResult ExternalLoginFailure()
        {
            return View();
        }

        [ChildActionOnly]
        public ActionResult RemoveAccountList()
        {
            var linkedAccounts = UserManager.GetLogins(User.Identity.GetUserId());
            ViewBag.ShowRemoveButton = HasPassword() || linkedAccounts.Count > 1;
            return (ActionResult)PartialView("_RemoveAccountPartial", linkedAccounts);
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing && UserManager != null)
            {
                UserManager.Dispose();
                UserManager = null;
            }
            base.Dispose(disposing);
        }

        #region Helpers
        // Used for XSRF protection when adding external logins
        private const string XsrfKey = "XsrfId";

        private IAuthenticationManager AuthenticationManager
        {
            get
            {
                return HttpContext.GetOwinContext().Authentication;
            }
        }

        private async Task SignInAsync(ApplicationUser user, bool isPersistent)
        {
            AuthenticationManager.SignOut(DefaultAuthenticationTypes.ExternalCookie);
            var identity = await UserManager.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie);
            AuthenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = isPersistent }, identity);
        }

        private void AddErrors(IdentityResult result)
        {
            foreach (var error in result.Errors)
            {
                ModelState.AddModelError(string.Empty, error);
            }
        }

        private bool HasPassword()
        {
            try
            {
                var user = UserManager.FindById(User.Identity.GetUserId());
                if (user != null)
                {
                    return user.PasswordHash != null;
                }
                return false;
            }
            catch (Exception ex)
            {
                logger.Error(ex.ToString());
                throw;
            }
        }

        public enum ManageMessageId
        {
            ChangePasswordSuccess,
            SetPasswordSuccess,
            RemoveLoginSuccess,
            Error
        }

        private ActionResult RedirectToLocal(string returnUrl)
        {
            if (Url.IsLocalUrl(returnUrl))
            {
                return Redirect(returnUrl);
            }
            else
            {
                return RedirectToAction("Manage", "Home");
            }
        }

        private class ChallengeResult : HttpUnauthorizedResult
        {
            public ChallengeResult(string provider, string redirectUri)
                : this(provider, redirectUri, null)
            {
            }

            public ChallengeResult(string provider, string redirectUri, string userId)
            {
                LoginProvider = provider;
                RedirectUri = redirectUri;
                UserId = userId;
            }

            public string LoginProvider { get; set; }
            public string RedirectUri { get; set; }
            public string UserId { get; set; }

            public override void ExecuteResult(ControllerContext context)
            {
                var properties = new AuthenticationProperties() { RedirectUri = RedirectUri };
                if (UserId != null)
                {
                    properties.Dictionary[XsrfKey] = UserId;
                }
                if (context != null)
                {
                    context.HttpContext.GetOwinContext().Authentication.Challenge(properties, LoginProvider);
                }

            }
        }
        #endregion

        private string GetFunction()
        {
            return "Chức năng đăng nhập - AccountController";
        }

        private List<string> GetUrlInRole(List<MenuModel> menuList)
        {
            try
            {
                List<string> url = new List<string>();
                if (menuList == null)
                    return url;
                url.Add("/Enumerator/AccountChangePass");
                url.Add("/Home/DowloadFile");
                url.Add("/Home/Manage");
                url.Add("/Home/WatchVideo");
                url.Add("/Home/PDFDisplay");
                url.Add("/Kehoachnam/Downloadfile");
                int length = menuList.Count;
                for (int i = 0; i < length; i++)
                {
                    if (!url.Contains(menuList[i].MenuUrl))
                    {
                        url.Add(menuList[i].MenuUrl);
                    }
                }
                return url;
            }
            catch (Exception ex)
            {
                logger.Error(ex.ToString());
                throw;
            }
        }

        [AllowAnonymous]
        public ActionResult AccountForgetPass()
        {
            return View();
        }

        [HttpPost]
        [AllowAnonymous]
        [ValidateInput(false)]
        public JsonResult ResetPassWord(string UserName, string Email)
        {
            try
            {
                bool exits = false;
                //using (WebClient wc = new WebClient())
                //{
                //    Helper.SetHeaderInfo(wc, "ResetPassWordByforget");
                //    string BoolChangePass = wc.DownloadString(administratorServiceUrl + "ResetPassWordByforget" + "/" + UserName + "/" + Email + "/" + CommonData.AppCode);
                //    exits = Convert.ToBoolean(BoolChangePass);
                //}
                return Json(exits, JsonRequestBehavior.AllowGet);
            }
            catch (Exception ex)
            {
                logger.Error(ex.ToString());
                throw;
            }
        }

    }

    #endregion

    #region -------------------OTHER CLASS ------------------------
    public interface IFormsAuthentication
    {
        void SignIn(string userName, bool createPersistentCookie);
        void SignOut();
    }

    public class FormsAuthenticationService : IFormsAuthentication
    {
        public void SignIn(string userName, bool createPersistentCookie)
        {
            FormsAuthentication.SetAuthCookie(userName, createPersistentCookie);
        }

        public void SignOut()
        {
            FormsAuthentication.SignOut();
        }
    }
    #endregion
}